package info.motteke.qjdbc;

import info.motteke.qjdbc.dto.DtoMeta;
import info.motteke.qjdbc.dto.DtoMetaPool;
import info.motteke.qjdbc.exception.QuickJDBCException;
import info.motteke.qjdbc.operation.delete.Delete;
import info.motteke.qjdbc.operation.insert.Insert;
import info.motteke.qjdbc.operation.select.Select;
import info.motteke.qjdbc.operation.update.Update;
import java.util.ArrayList;
import java.util.List;

/**
 * データベースへのアクセスを行うためのインターフェースを提供します。
 *
 * @author YWak
 *
 */
public final class DB {

    /**
     * データベースから値の取得を行います。
     *
     * @param <E>
     * @param clazz
     * @return
     */
    public static <E> Select<E> select(Class<E> clazz) {
        return select(clazz, null);
    }

    /**
     * データベースから検索します。
     * 指定したクラスを値の保持に利用します。
     *
     * @param <E>
     *            値を保持するクラス
     * @param clazz
     *            値を保持するクラス
     * @param table
     *            検索に利用するテーブル名
     */
    public static <E> Select<E> select(Class<E> clazz, String table) {
        check();
        return null;
    }

    /**
     * リストに含まれるオブジェクトが持つ値をデータベースに反映します。
     * @param <E>
     * @param list
     * @return
     */
    public static <E> int[] update(List<E> list) {
        check();
        return new Update<E>(getDtoMeta(list)).execute(list);
    }

    /**
     * オブジェクトが持つ値をデータベースに反映します。
     * @param <E>
     * @param obj
     * @return
     */
    public static <E> int update(E obj) {
        return update(asList(obj))[0];
    }

    /**
     * リストに含まれるオブジェクトをデータベースから削除します。
     * @param <E>
     * @param list
     * @return
     */
    public static <E> int[] delete(List<E> list) {
        check();
        return new Delete<E>(getDtoMeta(list)).execute(list);
    }

    /**
     * オブジェクトをデータベースから削除します。
     * @param <E>
     * @param obj
     * @return
     */
    public static <E> int delete(E obj) {
        return delete(asList(obj))[0];
    }

    /**
     * リストに含まれるオブジェクトをデータベースに追加します。
     * @param <E>
     * @param list
     * @return
     */
    public static <E> int[] insert(List<E> list) {
        check();
        return new Insert<E>(getDtoMeta(list)).execute(list);
    }

    /**
     * オブジェクトをデータベースに追加します。
     * @param <E>
     * @param obj
     * @return
     */
    public static <E> int insert(E obj) {
        return insert(asList(obj))[0];
    }

    private static void check() {
        if (!QuickJDBCProperties.isLoaded()) {
            throw new QuickJDBCException("プロパティを読み込んでいません。");
        }
    }

    @SuppressWarnings("unchecked")
    private static <E> DtoMeta<E> getDtoMeta(List<E> list) {
        return (DtoMeta<E>) DtoMetaPool.get(getElement(list).getClass());
    }

    private static <E> E getElement(List<E> list) {
        if (list == null) {
            return null;
        }
        if (list.size() == 0) {
            return null;
        }
        for (E obj : list) {
            if (obj != null) {
                return obj;
            }
        }
        return null;
    }

    private static <E> List<E> asList(E obj) {
        List<E> list = new ArrayList<E>();
        list.add(obj);

        return list;
    }
}
